#ifndef _core_switch_detail_switch_impl_hpp_
#define _core_switch_detail_switch_impl_hpp_

/** \file switch_impl.hpp
 *  \author Adrian Schweizer
 *  \created  $Mo 11 Feb 08:33:01 pm CET 2008 schwadri@SchwadriLaptop.local$
 *  \modified $Mo 11 Feb 08:39:31 pm CET 2008 schwadri@SchwadriLaptop.local$
 */

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/iteration/local.hpp>

#include <boost/fusion/sequence/intrinsic/at.hpp>
#include "at_impl.hpp"

#include <boost/fusion/sequence/intrinsic/at_key.hpp>
#include "at_key_impl.hpp"

#include <boost/fusion/sequence/intrinsic/value_at.hpp>
#include "value_at_impl.hpp"

#include "../case_sequence.hpp"
#include "case_invoker.hpp"
#include "tag_of.hpp"

namespace core {

    struct default_label;

    namespace detail {

        template<std::size_t n>
            struct get_impl;

        #define CORE_SWITCH_GENERATE_CASE(z,n,cases)                        \
            case result_of::value_at_c<Cases,n>::type::label::value:        \
                return at_c<n>(cases)();                                    \
                break;


        #define CORE_SWITCH_GENERATE_IMPL(n)                                \
            struct BOOST_PP_CAT(impl_,n)                                    \
            {                                                               \
                template<typename R, typename Key, typename Cases>          \
                    static R eval(Key key, const Cases& cases)              \
                    {                                                       \
                        using namespace boost::fusion;                      \
                        switch(key)                                         \
                        {                                                   \
                        BOOST_PP_REPEAT(n,CORE_SWITCH_GENERATE_CASE,cases)  \
                        default:                                            \
                            return at_key<core::default_label>(cases)(key); \
                        }                                                   \
                    }                                                       \
            };                                                              \
            template<>                                                      \
                struct get_impl<n>                                          \
                {                                                           \
                    typedef BOOST_PP_CAT(impl_,n) type;                     \
                };


        #define BOOST_PP_LOCAL_MACRO   CORE_SWITCH_GENERATE_IMPL
        #define BOOST_PP_LOCAL_LIMITS (0, CORE_SWITCH_LIMIT_CASES)
        //DO NOT REMOVE WHITESPACE   ^
        #include BOOST_PP_LOCAL_ITERATE()

        #undef CORE_SWITCH_GENERATE_IMPL
        #undef CORE_SWITCH_GENERATE_CASE

    }   //namespace detail

} // namespace core

#endif // _core_switch_detail_switch_impl_hpp_
